//
//  BasePageViewController.swift
//  ShangYouNews
//
//  Created by wangkun on 2017/5/3.
//  Copyright © 2017年 baymax. All rights reserved.
//

import UIKit

@objc public protocol PageViewControllerDelegate : NSObjectProtocol{
    /// 内容页切换委托
    ///
    /// - Parameters:
    ///   - fromIndex: 来源下标
    ///   - toIndex:   目标下标
    @objc optional func didChangeToIndex(fromIndex: Int ,toIndex:Int)
    
    /// 滑动过程中监控滑动距离
    ///
    /// - Parameters:
    ///   - toIndex:  目标下标
    ///   - percent:  拖动距离
    ///   - animated: 是否完成拖动
    @objc optional func didScroll(fromIndex : Int,toIndex: Int ,percent:CGFloat)
}

@objc public protocol PageViewControllerDataSource : NSObjectProtocol {
    /// 总页数
    ///
    /// - Returns: 总页数
    func numberForViewPager() -> Int
    
    /// 获取指定位置的ViewController
    ///
    /// - Parameter index: 位置
    /// - Returns: ViewController
    func contentViewControllerAtIndex(index : Int) -> UIViewController
    
    /// 距顶部高度
    ///
    /// - Returns: 高度
    @objc optional func contentOffsetTop() -> CGFloat
}

open class BasePageViewController: BaseViewController {

    var pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    var scrollPage : UIScrollView?
    var pageView : UIView?
    
    var dicViewController : Dictionary<Int, UIViewController> = Dictionary<Int,UIViewController>()
    var pageCount : Int = 0
    var currentIndex : Int = 0
    var prepareIndex : Int = 0
    var offsetTop : CGFloat!
    
    var delegate : PageViewControllerDelegate?
    var dataSource : PageViewControllerDataSource?
    
    override open func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        
        self.addChildViewController(pageViewController)
        pageView = pageViewController.view
        self.view.addSubview(pageView!)
        pageView?.snp.makeConstraints { (make) in
            make.edges.equalTo(UIEdgeInsets.zero);
        }
        pageViewController.delegate = self
        pageViewController.dataSource = self
        
        for  v in pageViewController.view.subviews {
            if v.isKind(of: UIScrollView.classForCoder()) {
                scrollPage = v as? UIScrollView
                scrollPage?.delegate = self
                scrollPage?.showsVerticalScrollIndicator = false
                scrollPage?.showsHorizontalScrollIndicator = false
                break
            }
        }
        
        self.reloadData()
    }
    
    func jumpToIndex(index : Int) {
        guard index < pageCount && index >= 0 && index != self.currentIndex else {
            return
        }
        currentIndex = index
        let viewController = viewControllerAtIndex(index: index)
        pageViewController.setViewControllers([viewController!], direction: .forward, animated: false, completion: nil)
        
    }
    
    func viewControllerAtIndex(index : Int) -> UIViewController? {
        if index < pageCount {
            if dicViewController[index] == nil {
                var viewController : UIViewController?
                viewController = dataSource?.contentViewControllerAtIndex(index: index)
                dicViewController.updateValue(viewController ?? UIViewController(), forKey: index)
            }
            return dicViewController[index] 
        }
        return nil//UIViewController()
    }
    
    func reloadData() {
        dicViewController.removeAll()
        if dataSource != nil {
            pageCount = (dataSource?.numberForViewPager())!
            if pageCount > 0 {
                if currentIndex >= pageCount {
                    currentIndex = 0
                }
                self.pageViewController.setViewControllers([viewControllerAtIndex(index: self.currentIndex)!], direction: .reverse, animated: false, completion: nil)
            }
            offsetTop = dataSource?.contentOffsetTop?()
            if offsetTop != nil {
                pageView?.snp.remakeConstraints { (make) in
                    make.edges.equalTo(UIEdgeInsetsMake(offsetTop!, 0, 0, 0));
                }
            }
        }
    }
    
    override open func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

extension BasePageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate{
    
    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        
        if currentIndex == pageCount - 1 {
            return nil
        }
        let vc = viewControllerAtIndex(index: currentIndex + 1)
        return vc
    }
    
    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        if currentIndex == 0 {
            return nil
        }
        let vc = viewControllerAtIndex(index: currentIndex - 1)
        return vc
    }
    
    
}


extension BasePageViewController : UIScrollViewDelegate{
    
    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard pageCount > 0 else{
            return
        }
        let contentoffSet = scrollView.contentOffset
        var toIndex : Int = prepareIndex
        if scrollView.contentOffset.x > scrollView.bounds.width {
            toIndex = (toIndex + 1) < pageCount ? (toIndex + 1) : pageCount - 1
        } else if scrollView.contentOffset.x < scrollView.bounds.width {
            toIndex = toIndex - 1 < 0 ? 0 : (toIndex - 1)
        }
        toIndex = toIndex < 0 ? 0 : toIndex
        toIndex = toIndex >= pageCount ? pageCount - 1 : toIndex
        
        if toIndex != prepareIndex{
            delegate?.didScroll?(fromIndex: self.prepareIndex, toIndex: toIndex, percent: abs(contentoffSet.x - scrollView.bounds.width) / scrollView.bounds.width)
        }
        
    }
    
    public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        
        let idx = Int(targetContentOffset.pointee.x / scrollView.bounds.size.width) - 1
        self.currentIndex += idx
    }
    
    public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        self.prepareIndex = self.currentIndex
    }
    
    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        delegate?.didChangeToIndex?(fromIndex: self.prepareIndex, toIndex: self.currentIndex)
        self.prepareIndex = self.currentIndex
    }
}
